﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
namespace com.susi.util.toolkit
{
#if ODIN_INSPECTOR
    [ShowInInspector][LabelText("属性表")]
#endif
    public class PropertySource : IPropertySource, IEnumerable<string>
    {
#if ODIN_INSPECTOR
        [ShowInInspector][LabelText("数字")]
#endif
        Dictionary<string, float> mFloDic = new Dictionary<string, float>();
#if ODIN_INSPECTOR
        [ShowInInspector][LabelText("字符串")]
#endif
        Dictionary<string, string> mStrDic = new Dictionary<string, string>();

        public IEnumerable<string> Keys => this;
        public void Set(string key, float value)
        {
            mStrDic.Remove(key);
            mFloDic.AddOrReplaceKV(key, value);
        }
        public void Set(string key, string value)
        {
            mFloDic.Remove(key);
            mStrDic.AddOrReplaceKV(key, value);
        }
        public void Set(KeyValuePair<string, float> kvp)
        {
            Set(kvp.Key, kvp.Value);
        }
        public void Set(KeyValuePair<string, string> kvp)
        {
            Set(kvp.Key, kvp.Value);
        }
        public void Set(IDictionary<string, float> flodic)
        {
            foreach (var kv in flodic) Set(kv);
        }
        public void Set(IDictionary<string, string> strdic)
        {
            foreach (var kv in strdic) Set(kv);
        }
        public void Set(IEnumerable<KeyValuePair<string, float>> kvps)
        {
            foreach (var kv in kvps) Set(kv);
        }
        public void Set(IEnumerable<KeyValuePair<string, string>> kvps)
        {
            foreach (var kv in kvps) Set(kv);
        }
        public void Set(string key)
        {
            mFloDic.Remove(key);
            mStrDic.Remove(key);
        }

        public bool TryGet(string key, out float value)
        {
            return mFloDic.TryGetValue(key, out value);
        }
        public bool TryGet(string key, out string value)
        {
            return mStrDic.TryGetValue(key, out value);
        }

        public bool ContainsFloKey(string key)
        {
            return mFloDic.ContainsKey(key);
        }
        public bool ContainsStrKey(string key)
        {
            return mStrDic.ContainsKey(key);
        }
        public bool ContainsKey(string key) => ContainsFloKey(key) || ContainsStrKey(key);

        IEnumerator<string> IEnumerable<string>.GetEnumerator()
        {
            return new KeyEnumerator(this);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new KeyEnumerator(this);
        }

        public float GetFlo(string key)
        {
            return mFloDic[key];
        }

        public string GetStr(string key)
        {
            return mStrDic[key];
        }

        private class KeyEnumerator : IEnumerator<string>
        {
            IEnumerator<IEnumerator<string>> enums;
            public KeyEnumerator(PropertySource propertySource)
            {
                var item = new IEnumerator<string>[] {
                    propertySource.mFloDic.Keys.GetEnumerator(),
                    propertySource.mStrDic.Keys.GetEnumerator(),
                    };
                enums = item.AsEnumerable().GetEnumerator();
            }

            public string Current => enums.Current.Current;

            object IEnumerator.Current => Current;

            public void Dispose()
            {
                enums.Reset();
                while (enums.MoveNext()) enums.Current.Dispose();
                enums.Dispose();
            }

            public bool MoveNext()
            {
                if (enums.Current.MoveNext()) return true;
                else if (enums.MoveNext() && enums.Current.MoveNext()) return true;
                return false;
            }

            public void Reset()
            {
                enums.Reset();
                while (enums.MoveNext()) enums.Current.Reset();
                enums.Reset();
            }
        }

    }
}
